//
// Created by bangsun on 2022/11/11.
//

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdatomic.h>
#include <stdio.h>
#include "include/deque.h"
#include "include/switch.h"


int expand_deque(deque *deque) {
    int new_cap = deque->capacity << 1;
    void **new_data = calloc(new_cap, sizeof(void *));
    memmove(new_data, deque->data, deque->capacity * sizeof(void *));
    if (deque->head > deque->tail) {
        int num_ele = deque->capacity - deque->head;
        memmove(new_data + new_cap - num_ele, deque->data + deque->head, num_ele * sizeof(void *));
        deque->head = new_cap - num_ele;
    }
    free(deque->data);
    deque->data = new_data;
    deque->capacity = new_cap;
    return new_cap;
}

void free_deque(deque *deque) {
    free(deque->data);
    free(deque);
}

deque *create_deque() {
    deque *deque = malloc(sizeof(struct deque));
    init_deque(deque);
    return deque;
}


void init_deque(deque *deque) {
    void **data = calloc(DEFAULT_CAPACITY, sizeof(void *));
    deque->capacity = DEFAULT_CAPACITY;
    deque->size = 0;
    deque->data = data;
    deque->head = 0;
    deque->tail = -1;
}

int add_first(deque *deque, void *val) {
    if (deque->size == deque->capacity) {
        expand_deque(deque);
    }
    deque->head -= 1;
    if (deque->head < 0) {
        deque->head += deque->capacity;
    }
    deque->data[deque->head] = val;
    return ++deque->size;
}

int add_last(deque *deque, void *val) {
    if (deque->size == deque->capacity) {
        expand_deque(deque);
    }
    deque->tail = (deque->tail + 1) % deque->capacity;
    deque->data[deque->tail] = val;

    return ++deque->size;
}

void *poll_last(deque *deque) {
    if (deque->size == 0) {
        return NULL;
    }
    if (deque->tail < 0) {
        deque->tail += deque->capacity;
    }
    deque->size--;
    return deque->data[deque->tail--];
}

void *poll_first(deque *deque) {
    if (deque->size == 0) {
        return NULL;
    }
    void *ret_val = deque->data[deque->head++];
    deque->head %= deque->capacity;
    deque->size--;

    return ret_val;
}

void *peek_last(deque *deque) {
    if (deque->size == 0) {
        return NULL;
    }
    if (deque->tail < 0) {
        deque->tail += deque->capacity;
    }
    return deque->data[deque->tail];
}

void *peek_first(deque *deque) {
    if (deque->size == 0) {
        return NULL;
    }
    return deque->data[deque->head];
}

void print_deque(deque *deque) {
    printf("[");
    int i = 0, iter = deque->head;

    for (; i < deque->size; i++) {
        Loutine *loutine = (Loutine *) deque->data[iter];
        printf("arg:%x, ", loutine->arg);
        iter = (iter + 1) % deque->capacity;
    }
    printf("]\n");
    fflush(stdout);

}


